﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Text;

namespace Silver3D.Math
{
    [TypeConverter(typeof(Vec4Converter))]
    public class Vec4List : List<Vec4>
    {
        public Vec4List()
            : base()
        {
        }

        public Vec4List(int capacity)
            : base(capacity)
        {
        }

        public Vec4List(IEnumerable<Vec4> collection)
            : base(collection)
        {
        }
    }

    public class Vec4Converter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return (sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return (destinationType == typeof(string)) || base.CanConvertTo(context, destinationType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            string list = value as string;
            if (list == null) return base.ConvertFrom(context, culture, value);

            double[] d = ArrayParser.GetDoubleArray(list);
            if (d == null) return null;

            int count = d.Length / 4;
            if (count * 4 != d.Length)
                throw new Silver3DException("Vec4List cannot be built from {0} elements.", d.Length);

            Vec4List v = new Vec4List(count);
            for (int i = 0; i < d.Length; i += 4)
                v.Add(new Vec4(d[i], d[i + 1], d[i + 2], d[i + 3]));

            return v;
        }

        private void Append(StringBuilder sb, Vec4 v)
        {
            sb.Append(v.X);
            sb.Append(' ');
            sb.Append(v.Y);
            sb.Append(' ');
            sb.Append(v.Z);
            sb.Append(' ');
            sb.Append(v.W);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            Vec4List v = value as Vec4List;
            if (v == null) return base.ConvertTo(context, culture, value, destinationType);

            StringBuilder sb = new StringBuilder(v.Count * 4 * 4);
            if (v.Count > 0) Append(sb, v[0]);
            for (int i = 1; i < v.Count; ++i)
            {
                sb.Append(' ');
                Append(sb, v[i]);
            }
            return sb.ToString();
        }
    }
}
